package com.twobu.twobuinsight.service.impl;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.twobu.twobuinsight.dto.TaskHistoryDTO;
import com.twobu.twobuinsight.dto.TaskHistorySimpleDTO;
import com.twobu.twobuinsight.security.UserContextHolder;
import com.twobu.twobuinsight.service.TaskHistoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class TaskHistoryServiceImpl implements TaskHistoryService {

    private static final String TASK_HISTORY_KEY_PREFIX = "task:history:user:";
    private static final String TASK_HISTORY_DETAIL_KEY_PREFIX = "task:history:detail:";

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;



    @Override
    public TaskHistoryDTO getTaskHistoryDetail(String taskId) {
        log.info("从Redis获取任务历史详情, taskId: {}", taskId);

        // 先从任务详情缓存中查找
        String detailKey = TASK_HISTORY_DETAIL_KEY_PREFIX + taskId;
        Object detailObj = redisTemplate.opsForValue().get(detailKey);

        if (detailObj != null) {
            try {
                return objectMapper.readValue(detailObj.toString(), TaskHistoryDTO.class);
            } catch (JsonProcessingException e) {
                log.error("解析任务历史详情JSON失败", e);
            }
        }

        // 如果详情缓存中没有，则遍历所有用户的任务历史
        Set<String> keys = redisTemplate.keys(TASK_HISTORY_KEY_PREFIX + "*");
        if (keys != null) {
            for (String key : keys) {
                Object taskObj = redisTemplate.opsForHash().get(key, taskId);
                if (taskObj != null) {
                    try {
                        TaskHistoryDTO dto = objectMapper.readValue(taskObj.toString(), TaskHistoryDTO.class);
                        // 缓存到详情key中
                        redisTemplate.opsForValue().set(detailKey, taskObj);
                        return dto;
                    } catch (JsonProcessingException e) {
                        log.error("解析任务历史JSON失败", e);
                    }
                }
            }
        }

        // 如果Redis中没有找到，生成模拟数据
        log.info("Redis中没有找到任务历史详情，生成模拟数据");
        TaskHistoryDTO mockDetail = generateMockTaskHistoryDetail(taskId);
        if (mockDetail != null) {
            try {
                String json = objectMapper.writeValueAsString(mockDetail);
                redisTemplate.opsForValue().set(detailKey, json);

                // 同时保存到用户的任务历史中
                String userKey = TASK_HISTORY_KEY_PREFIX + mockDetail.getUserId();
                redisTemplate.opsForHash().put(userKey, taskId, json);
            } catch (JsonProcessingException e) {
                log.error("序列化任务历史详情失败", e);
            }
        }

        return mockDetail;
    }

    @Override
    public void saveTaskHistory(TaskHistoryDTO taskHistory) {
        if (taskHistory == null || !StringUtils.hasText(taskHistory.getTaskId())
                || !StringUtils.hasText(taskHistory.getUserId())) {
            log.error("保存任务历史失败：参数无效");
            return;
        }

        try {
            // 序列化为JSON
            String json = objectMapper.writeValueAsString(taskHistory);

            // 保存到用户的任务历史Hash中
            String userKey = TASK_HISTORY_KEY_PREFIX + taskHistory.getUserId();
            redisTemplate.opsForHash().put(userKey, taskHistory.getTaskId(), json);

            // 同时保存到任务详情缓存中
            String detailKey = TASK_HISTORY_DETAIL_KEY_PREFIX + taskHistory.getTaskId();
            redisTemplate.opsForValue().set(detailKey, json);

            log.info("保存任务历史成功, taskId: {}, userId: {}",
                    taskHistory.getTaskId(), taskHistory.getUserId());
        } catch (JsonProcessingException e) {
            log.error("序列化任务历史失败", e);
        }
    }

    /**
     * 批量保存任务历史
     */
    private void saveTaskHistoryBatch(String userId, List<TaskHistoryDTO> taskHistoryList) {
        if (taskHistoryList == null || taskHistoryList.isEmpty()) {
            return;
        }

        String userKey = TASK_HISTORY_KEY_PREFIX + userId;
        Map<String, String> entries = new HashMap<>();

        for (TaskHistoryDTO dto : taskHistoryList) {
            try {
                String json = objectMapper.writeValueAsString(dto);
                entries.put(dto.getTaskId(), json);

                // 同时保存到任务详情缓存中
                String detailKey = TASK_HISTORY_DETAIL_KEY_PREFIX + dto.getTaskId();
                redisTemplate.opsForValue().set(detailKey, json);
            } catch (JsonProcessingException e) {
                log.error("序列化任务历史失败", e);
            }
        }

        if (!entries.isEmpty()) {
            redisTemplate.opsForHash().putAll(userKey, entries);
            log.info("批量保存任务历史成功, userId: {}, count: {}", userId, entries.size());
        }
    }

    /**
     * 生成模拟任务历史数据
     */
    private List<TaskHistoryDTO> generateMockTaskHistory(String userId) {
        List<TaskHistoryDTO> mockData = new ArrayList<>();

        // 模拟5条历史记录
        String[] domains = {"hkex", "sse", "szse", "finance", "tech"};
        String[] models = {"qianwen", "gpt4", "claude", "llama"};
        String[] instructions = {
            "分析该公司最新财报中的关键财务指标",
            "分析该行业近期的发展趋势和技术创新",
            "评估投资该行业的主要风险因素",
            "分析近期相关政策法规变化对该行业的影响",
            "分析该行业的竞争格局和主要参与者"
        };

        Random random = new Random();

        for (int i = 0; i < 5; i++) {
            LocalDateTime createTime = LocalDateTime.now().minusDays(random.nextInt(30));
            LocalDateTime finishTime = createTime.plusHours(random.nextInt(3));

            TaskHistoryDTO dto = TaskHistoryDTO.builder()
                    .taskId("task-" + UUID.randomUUID().toString().substring(0, 8))
                    .userId(userId)
                    .userInstruction(instructions[i])
                    .domain(domains[random.nextInt(domains.length)])
                    .model(models[random.nextInt(models.length)])
                    .fromDate(String.format("%d%02d%02d",
                            2023, random.nextInt(12) + 1, random.nextInt(28) + 1))
                    .toDate(String.format("%d%02d%02d",
                            2023, random.nextInt(12) + 1, random.nextInt(28) + 1))
                    .deep(String.valueOf(random.nextInt(2) + 1))
                    .status("completed")
                    .createTime(createTime)
                    .finishTime(finishTime)
                    .resultSummary("该研究分析了行业趋势和关键指标，发现..." + (i + 1))
                    .build();

            mockData.add(dto);
        }

        return mockData;
    }

    /**
     * 生成模拟任务历史详情
     */
    private TaskHistoryDTO generateMockTaskHistoryDetail(String taskId) {
        Random random = new Random();

        LocalDateTime createTime = LocalDateTime.now().minusDays(random.nextInt(30));
        LocalDateTime finishTime = createTime.plusHours(random.nextInt(3));

        String[] domains = {"hkex", "sse", "szse", "finance", "tech"};
        String[] models = {"qianwen", "gpt4", "claude", "llama"};
        String[] userIds = {"user1", "user2", "admin"};

        return TaskHistoryDTO.builder()
                .taskId(taskId)
                .userId(userIds[random.nextInt(userIds.length)])
                .userInstruction("分析该公司最新财报中的关键财务指标和业绩变化")
                .domain(domains[random.nextInt(domains.length)])
                .model(models[random.nextInt(models.length)])
                .fromDate(String.format("%d%02d%02d",
                        2023, random.nextInt(12) + 1, random.nextInt(28) + 1))
                .toDate(String.format("%d%02d%02d",
                        2023, random.nextInt(12) + 1, random.nextInt(28) + 1))
                .deep(String.valueOf(random.nextInt(2) + 1))
                .status("completed")
                .createTime(createTime)
                .finishTime(finishTime)
                .resultSummary("该研究分析了行业趋势和关键指标，发现公司在过去一年中营收增长了15%，但净利润下降了3%。主要原因是研发投入增加和市场扩张。未来展望方面，公司计划在新兴市场加大投入，预计将在2-3年内带来新的增长点。")
                .build();
    }

    @Override
    public List<TaskHistorySimpleDTO> getUserTaskHistorySimple(String userId) {
        log.info("从Redis获取用户任务历史简化列表, userId: {}", userId);

        String key = "user:taskId:mapper:" + UserContextHolder.getCurrentUserId();
       List<TaskHistorySimpleDTO> result = new ArrayList<>();
        Set<String> members = stringRedisTemplate.opsForSet().members(key);
        for (String member : members) {
            TaskHistorySimpleDTO bean = JSONUtil.toBean(member, TaskHistorySimpleDTO.class);
            result.add(bean);
        }
        // 按创建时间倒序排序
        result.sort(Comparator.comparing(TaskHistorySimpleDTO::getCreateTime).reversed());
        return result;
    }
}
